package gnss

import (
	"dgo/goutils/utils"
)

type GnssSVEpochRtcmDecoder struct {
	rtcmRaw      *Rtcm3RawBufDecoder
	epoch        *GnssSVEpoch
	epochMsmN    int
	CopyRoughR   bool
	EpochNewFlag int8 // 每次都新建一个

	OutputMessageFunc func(s string, args ...interface{})
	OnRtcmDecodeErr   func(msgid uint16, err error)
	OnRtcmCrcFail     func(buf []byte, err error)
	OnRtcmDecodeBug   func(buf []byte, err error)

	/***
	  返回false则 不进行解码
	*/
	OnRtcmBuf func(msgid uint16, buf []byte) bool

	/**
	  checktype : 1, 非正常的完结, 0:有完结标志
	*/
	OnEpochFunc func(epoch *GnssSVEpoch, checktype int)

	OnSignConvert     Func_signconvert
	OnSignFreqGetFunc Func_GetFreq
}

func NewGnssSVEpochRtcmDecoder() *GnssSVEpochRtcmDecoder {
	rval := &GnssSVEpochRtcmDecoder{}
	rval.rtcmRaw = NewRtcm32RawBufDecoder("SVDec")
	rval.rtcmRaw.CopyBufOnRtcmBuf = false
	rval.init()
	return rval
}

func (this *GnssSVEpochRtcmDecoder) outputMessage(s string, args ...interface{}) {
	if this.OutputMessageFunc != nil {
		this.OutputMessageFunc(s, args...)
	} else {
		utils.Log.Debugf(s, args...)
	}
}

func (this *GnssSVEpochRtcmDecoder) onEpoch(checktype int) {
	if this.OnEpochFunc != nil && this.epoch != nil {
		this.OnEpochFunc(this.epoch, checktype)
		if this.EpochNewFlag == 1 {
			this.epoch = nil
		}
	}
	this.epochMsmN = 0
}

func (this *GnssSVEpochRtcmDecoder) initEpoch(msm RtcmRawMsm) {
	if this.EpochNewFlag == 1 {
		this.epoch = NewGnssSVEpoch()
	} else {
		if this.epoch == nil {
			this.epoch = NewGnssSVEpoch()
		}
		this.epoch.Reset()
	}

	this.epoch.TOW = msm.GetHeader().GetTOW()
	this.epoch.SmoothingInterval = msm.GetHeader().SmoothingInterval
	this.epoch.SmoothingType = msm.GetHeader().SmoothingType
	this.epoch.IODS = msm.GetHeader().IODS
	this.epoch.ClkSteering = msm.GetHeader().ClkSteering
	this.epoch.ExternalClk = msm.GetHeader().ExternalClk
	this.epoch.StaID = msm.GetHeader().StaID
}

func (this *GnssSVEpochRtcmDecoder) InputDone() {
	if this.epochMsmN > 0 {
		this.onEpoch(1)
	}
}

func (this *GnssSVEpochRtcmDecoder) onRtcmMsm(msm RtcmRawMsm) {
	if this.epochMsmN == 0 {
		this.initEpoch(msm)
	} else {
		if this.epoch.TOW != msm.GetHeader().GetTOW() {
			this.onEpoch(1)
			this.initEpoch(msm)
		}
	}
	GnssSvEpochFromRtcmMsm(this.epoch, msm, this.CopyRoughR, this.OnSignFreqGetFunc, this.OnSignConvert)
	this.epochMsmN++
	if msm.GetHeader().EpochEndFlag {
		this.onEpoch(0)
	}
}

func (this *GnssSVEpochRtcmDecoder) init() {
	this.rtcmRaw.OnRtcmBuf = func(rtcmBuf []byte) {
		this.InputRtcmBuf(rtcmBuf)
	}
	this.rtcmRaw.OnErr = func(errcode int, err error) bool {
		if errcode == RTCM_CRC_FAIL {
			if this.OnRtcmCrcFail != nil {
				this.OnRtcmCrcFail(this.rtcmRaw.GetRawBuf(), err)
			} else {
				this.outputMessage("%s", err.Error())
			}
		} else if errcode == RTCM_BUG_DATA {
			if this.OnRtcmDecodeBug != nil {
				this.OnRtcmDecodeBug(this.rtcmRaw.GetRawBuf(), err)
			} else {
				this.outputMessage("%s", err.Error())
			}
		}
		return true
	}
}

func (this *GnssSVEpochRtcmDecoder) InputBuf(buf []byte) {
	this.rtcmRaw.InputBuf(buf)
}

/*
rtcmBuf 包含头和CRC
*/
func (this *GnssSVEpochRtcmDecoder) InputRtcmBuf(rtcmBuf []byte) {
	msgid := uint16(GetRtcmMsgId(rtcmBuf, 24))
	if this.OnRtcmBuf != nil {
		if !this.OnRtcmBuf(uint16(msgid), rtcmBuf) {
			return
		}
	}

	if RtcmIsMsm4(msgid) {
		msm4 := NewRtcmRawMsm4()
		err := msm4.DecodeMsm(rtcmBuf)
		if err != nil {
			if this.OnRtcmDecodeErr != nil {
				this.OnRtcmDecodeErr(msgid, err)
			} else {
				this.outputMessage("[%s]%s", msgid, err.Error())
			}
		} else {
			this.onRtcmMsm(msm4)
		}
	} else if RtcmIsMsm5(msgid) {
		msm := NewRtcmRawMsm5()
		err := msm.DecodeMsm(rtcmBuf)
		if err != nil {
			if this.OnRtcmDecodeErr != nil {
				this.OnRtcmDecodeErr(msgid, err)
			} else {
				this.outputMessage("[%s]%s", msgid, err.Error())
			}
		} else {
			this.onRtcmMsm(msm)
		}
	} else if RtcmIsMsm7(msgid) {
		msm7 := NewRtcmRawMsm7()
		err := msm7.DecodeMsm(rtcmBuf)
		if err != nil {
			if this.OnRtcmDecodeErr != nil {
				this.OnRtcmDecodeErr(msgid, err)
			} else {
				this.outputMessage("[%s]%s", msgid, err.Error())
			}
		} else {
			this.onRtcmMsm(msm7)
		}
	}
}
